package com.iot.iotplus.filters;

import com.aliyun.core.utils.IOUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iot.iotplus.base.Result;
import com.iot.iotplus.entity.Tenant;
import com.iot.iotplus.utils.ResultUtil;
import com.iot.iotplus.utils.RsaUtils;
import io.jsonwebtoken.*;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.ResourceUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.List;

import java.io.IOException;
import java.io.InputStream;
import org.springframework.core.io.ClassPathResource;


/**
 * 继承BasicAuthenticationFilter，实现登录认证流程
 * 创建带AuthenticationManager参数构造器
 * 重写doFilterInternal自定义jwt令牌认证实现
 */
public class JwtFilter  extends BasicAuthenticationFilter {
    public JwtFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    public JwtFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
        super(authenticationManager, authenticationEntryPoint);
    }


    /**
     * 自定义过滤器，且配置在SpringSecurity的认证过滤器之前
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        if ("/tenant/login".equals(request.getRequestURI()) ||
                request.getRequestURL().toString().contains("SendMsg") ||
                request.getRequestURL().toString().contains("register") ||
                request.getRequestURL().toString().contains("auth/login") ||
                request.getRequestURL().toString().contains("third")
        ){
            chain.doFilter(request,response);
            return;
        }
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            return;
        }
        //获取请求头中的token，做校验
        String token = request.getHeader("token");
        InputStream inputStream = null;
        try {
            if (token == null) {
                doResponse(response, ResultUtil.unauthorized(null));
                return;
            }

            // 使用ClassPathResource加载资源
            ClassPathResource resource = new ClassPathResource("pub.txt");
            // 从资源中获取输入流
            inputStream = resource.getInputStream();
            // 读取输入流到字节数组
            byte[] allBytes = IOUtils.toByteArray(inputStream);
            PublicKey publicKey = RsaUtils.getPublicKey(allBytes);

            JwtParser parser = Jwts.parser();
            parser.setSigningKey(publicKey);
            Jwt parse = parser.parse(token);

            Claims claims = (Claims) parse.getBody();
            String id = claims.getId();
            String subject = claims.getSubject();
            String role = (String) claims.get("role");

            Tenant tenant = new Tenant();
            tenant.setId(id);
            tenant.setName(subject);
            //设置认证信息
            List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(role);

            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(tenant, null, authorities);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            chain.doFilter(request, response);
        } catch (ExpiredJwtException e) {
            doResponse(response, ResultUtil.unauthorized(null));
        } catch (Exception e) {
            e.printStackTrace();
            doResponse(response, ResultUtil.validateFailed());
        } finally {
            inputStream.close();
        }

    }
    private void doResponse(HttpServletResponse response, Result<Object> resultVO) throws IOException {
        String json = new ObjectMapper().writeValueAsString(resultVO);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json");
        PrintWriter writer = response.getWriter();
        writer.write(json);
        writer.flush();
        writer.close();
    }



}
